#ifndef FACET_H_INCLUDED
#define FACET_H_INCLUDED

#include "Vector3.h"
#include "Vertex.h"
#include <vector>
#include "Material.h"

namespace prog3d {

  class Soup;

/**
@file
@author F. Aubert
@brief Opérations sur les facettes
*/

typedef enum {NORMAL_FACE=1,DRAW_TEXTURE=32,NORMAL_VERTEX=16,DRAW_GRID=2,DRAW_FILL=4,DRAW_NO_GRID=0,DRAW_NO_FILL=0,DRAW_MTL=8} EDrawFace;
typedef enum {MOINS,PLUS} ESigne;


/**
@class Facet
@brief Représentation d'une facette (liste de références sur sommet).
*/
class Facet {
protected:
	/// ensemble des sommets
	AVertex vv;
	/// normale à la facette
	Vector3 n;
	/// ensemble des normales par sommets (permet de gérer les arêtes vives)
	AVector3 vn;
	/// ensemble des coordonnées de textures
	AVector3 vt;

	Material *_material;
	Material *_currentMaterial; /// pour éviter de switcher de materiel à chaque face

	unsigned int drawMode;
	Vector3 a;

	void init(Soup *o);
	Soup *_owner;
public:
	/// constructeur par défaut
	Facet(Soup *o);
	Facet(Soup *o,const Vector3 &a,const Vector3 &n);

  const AVertex &vertexList();
  const Vector3 &normal();
  const AVector3 &normalList();

  inline Soup *owner() {return _owner;}


	/// vacuité de la facette (vide si 0 sommet)
	bool isEmpty() const;

	/// normals per vertex in a face
	bool isNormal() const;

	/// création et adjonction du sommet construit à partir du  p
	Vertex *createVertex(const Vector3 &p);

	/// création et adjonction du sommet construit à partir du  p
	Vertex *addVertex(const Vector3 &p);

  Material *material();
  void material(Material *m);

	/// mode d'affichage. Exemple : DRAW_GRID | DRAW_FILL
	void setDrawMode(unsigned int mode);

	/// nombre de sommets de la facette
	unsigned int nbVertex() const;

	/// calcul la normale au polygone
	void computeNormal();
	/// trace la facette (remplissage si line = false)
	void draw();
	///
	void drawNormal(float k);

	/// donne la normale à la facette
	const Vector3 &normal() const;

	/// affecte la normale à la facette (normale du polygone)
	void setNormal(const Vector3 &n);

  /// number of normal in the face
  unsigned int nbNormal() const;

	/// donne la normale au sommet i (référence)
	Vector3 *getNormal(int i) const;

	/// donne le sommet i (référence)
	Vertex *getVertex(unsigned int i) const;

	/// donne la valeur du  du vertex i
	const  Vector3 &point(unsigned int i) const;

	const Vertex &vertex(unsigned int i,bool reference) const;
	Vertex *vertex(unsigned int i) const;


	/// donne le tableau des sommets
	AVertex &getAllVertex();
	/// ajoute un sommet au tableau des sommets
	void addVertex(Vertex *v);
	/// ajoute une normale au tableau des normales
	void addNormal(Vector3 *n);

	/// enleve un sommet de la face
	void erase(AVertex::iterator &v);

	/// détruit les sommets et normales (prudence : delete)
	void clean();
	/// remet à zéro les sommets (la facette ne détruira pas ses vertices)
	void clearVVertex();
	/// remet à zéro les normales (la facette ne détruira pas ses normales)
	void clearVNormal();

	/// remet à zéro les tableaux sommets et normales
	void clear();

	/// donne l'itérateur correspondant au premier sommet
	AVertex::iterator vertexBegin();
	/// donne l'itérateur correspondant au dernier sommet
	AVertex::iterator vertexEnd();
	/// return the vertex following i
	Vertex *vertexSucc(int i);
	/// return the vertex preceding i
	Vertex *vertexPred(int i);

	void eraseDuplicateVertex();

	/// print
	void print(const std::string &mesg);

	/// triangule (sommet par sommet). CU : doit être convexe pour un résultat correct
	void triangulate();

	/// return the index in the object (see class Soup) of the vertex number i.
	unsigned int indice(unsigned int i);


	/// texture
	void addTexCoord(Vector3 *t);
  Vector3 *texCoord(unsigned int i) const;

	virtual ~Facet();
};

/**
@class AFacet
@brief représentation d'une tableau de références de facette
*/


class AFacet:public Array<Facet> {
	unsigned int drawMode;
    public:
    AFacet() {drawMode=NORMAL_VERTEX | DRAW_FILL;}
    /// calcule toutes les normales aux facettes
    void computeNormal();
    ///
    void setDrawMode(unsigned int mode);
    /// trace toutes les facettes
    void draw();
    void drawNormal(float k);
};


}




#endif // FACET_H_INCLUDED
